import React, { memo, useCallback } from 'react';
import { usePrevious } from 'react-use';
import { isEqual } from 'lodash';
import { css, cx } from '@emotion/css';
import { InlineFormLabel, RadioButtonGroup } from '@grafana/ui';
import { PromQuery } from '../types';
import { PromExemplarField } from './PromExemplarField';
import { PrometheusDatasource } from '../datasource';

export interface PromExploreExtraFieldProps {
  query: PromQuery;
  onChange: (value: PromQuery) => void;
  onRunQuery: () => void;
  datasource: PrometheusDatasource;
}

export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
  ({ query, datasource, onChange, onRunQuery }) => {
    const rangeOptions = [
      { value: 'range', label: 'Range', description: 'Run query over a range of time.' },
      {
        value: 'instant',
        label: 'Instant',
        description: 'Run query against a single point in time. For this query, the "To" time is used.',
      },
      { value: 'both', label: 'Both', description: 'Run an Instant query and a Range query.' },
    ];

    const prevQuery = usePrevious(query);

    const onExemplarChange = useCallback(
      (exemplar: boolean) => {
        if (!isEqual(query, prevQuery) || exemplar !== query.exemplar) {
          onChange({ ...query, exemplar });
        }
      },
      [prevQuery, query, onChange]
    );

    function onChangeQueryStep(interval: string) {
      onChange({ ...query, interval });
    }

    function onStepChange(e: React.SyntheticEvent<HTMLInputElement>) {
      if (e.currentTarget.value !== query.interval) {
        onChangeQueryStep(e.currentTarget.value);
      }
    }

    function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
      if (e.key === 'Enter' && e.shiftKey) {
        onRunQuery();
      }
    }

    function onQueryTypeChange(queryType: string) {
      let nextQuery;
      if (queryType === 'instant') {
        nextQuery = { ...query, instant: true, range: false };
      } else if (queryType === 'range') {
        nextQuery = { ...query, instant: false, range: true };
      } else {
        nextQuery = { ...query, instant: true, range: true };
      }
      onChange(nextQuery);
    }

    return (
      <div aria-label="Prometheus extra field" className="gf-form-inline" data-testid={testIds.extraFieldEditor}>
        {/*Query type field*/}
        <div
          data-testid={testIds.queryTypeField}
          className={cx(
            'gf-form explore-input-margin',
            css`
              flex-wrap: nowrap;
            `
          )}
          aria-label="Query type field"
        >
          <InlineFormLabel width="auto">Query type</InlineFormLabel>

          <RadioButtonGroup
            options={rangeOptions}
            value={query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range'}
            onChange={onQueryTypeChange}
          />
        </div>
        {/*Step field*/}
        <div
          data-testid={testIds.stepField}
          className={cx(
            'gf-form',
            css`
              flex-wrap: nowrap;
            `
          )}
          aria-label="Step field"
        >
          <InlineFormLabel
            width={6}
            tooltip={
              'Time units and built-in variables can be used here, for example: $__interval, $__rate_interval, 5s, 1m, 3h, 1d, 1y (Default if no unit is specified: s)'
            }
          >
            Min step
          </InlineFormLabel>
          <input
            type={'text'}
            className="gf-form-input width-4"
            placeholder={'auto'}
            onChange={onStepChange}
            onKeyDown={onReturnKeyDown}
            value={query.interval ?? ''}
          />
        </div>

        <PromExemplarField onChange={onExemplarChange} datasource={datasource} query={query} />
      </div>
    );
  }
);

export const testIds = {
  extraFieldEditor: 'prom-editor-extra-field',
  stepField: 'prom-editor-extra-field-step',
  queryTypeField: 'prom-editor-extra-field-query-type',
};
